/*
 * User: user
 * Date: 16/02/2008
 * Time: 02:39:43
 */
package org.conann.instrument;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;

/**
 A transformer to weave the main method of the org.eclipse.jdt.internal.junit.runner.RemoteTestRunner, so that we can deploy the correct
 -aop.xml files before the test case class itself is loaded when running within Eclipse

 @author <a href="mailto:bill@jboss.org">Bill Burke</a>
 @version $Revision: 44099 $ */
@Deprecated
public class EclipseTestTransformer implements ClassFileTransformer {

    private AOPTransformer aopTransformer = new AOPTransformer();

    private boolean foundRemoteTestRunner;

    /** The main class when running tests from Eclipse */
    private static final String MAIN_CLASS = "org/eclipse/jdt/internal/junit/runner/RemoteTestRunner";

    /**
     If running from within Eclipse with the -javaagent:eclipse-agent.jar switch set, the EclipseTestTransformer weaves the
     org.eclipse.jdt.internal.junit.runner.RemoteTestRunner class to set this system property to the name of the test class
     run.
     */
    public static final String CLASSLOADER_DEPLOYED_XML = "jboss.aop.eclipse.test.xml.name";

    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        if (!foundRemoteTestRunner && className.equals(MAIN_CLASS)) {
            System.out.println("Found class " + className);
            return weaveRemoteTestRunner(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
        }
        return aopTransformer.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
    }

    private byte[] weaveRemoteTestRunner(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        try {
//            AspectManager manager = AspectManager.instance();
            ClassPool pool = null;
//            pool = manager.registerClassLoader(loader);
            CtClass remoteTestRunner = pool.get(MAIN_CLASS.replace('/', '.'));
            remoteTestRunner.defrost();

            CtMethod originalMain = remoteTestRunner.getMethod("main", "([Ljava/lang/String;)V");
            System.out.println("-----> Found CtMethod " + (originalMain != null));

            CtMethod wrapper = CtNewMethod.copy(originalMain, remoteTestRunner, null);
            originalMain.setName("originalMain");

            String body = "{" + "  org.jboss.aop.eclipsesupport.EclipseTestTransformer.recordClassNameAndDeployXml($$);" + "  originalMain($$);" + "}";

            wrapper.setBody(body);
            remoteTestRunner.addMethod(wrapper);

            remoteTestRunner.debugWriteFile();
            return remoteTestRunner.toBytecode();
        } catch (Exception e) {
            // AutoGenerated
            System.out.println("====> Exception " + e);
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static void recordClassNameAndDeployXml(String[] args) throws Exception {
        //This code is lifted from RemoteTestRunner
        String[] fTestClassNames = null;
        for (int i = 0; i < args.length; i++) {
            if (args[i].toLowerCase().equals("-classnames") || args[i].toLowerCase().equals("-classname")) {
                List<String> list = new ArrayList<String>();
                for (int j = i + 1; j < args.length; j++) {
                    if (args[j].startsWith("-")) {
                        break;
                    }
                    list.add(args[j]);
                }

                fTestClassNames = list.toArray(new String[list.size()]);
            }
        }

        if (fTestClassNames == null || fTestClassNames.length == 0) {
            throw new RuntimeException("No classnames could be found");
        }
        if (fTestClassNames.length > 1) {
            throw new RuntimeException("Only one class name is supported");
        }

        deployXmlForEclipse(fTestClassNames[0]);
    }

    /**
     This will be initiated from the woven RemoteTestRunner classs to deploy the xml for the testcase UNLESS
     the jboss.aop.path system property has been set.
     */
    public static void deployXmlForEclipse(String testClass) throws Exception {
        if (System.getProperty("jboss.aop.path") != null) {
            return;
        }

        //Determine the url of the -aop.xml file depending on test package name
        String testName = null;
        if (testClass.contains(".regression.")) {
            //Handle the regresssion test differently
            testName = "regression";
        } else {
            int dot = testClass.lastIndexOf('.');
            String packageName = testClass.substring(0, dot);
            dot = packageName.lastIndexOf('.');
            testName = packageName.substring(dot + 1);
        }

        testName = "test/" + testName + "/jboss-aop.xml";
        URL url = Thread.currentThread().getContextClassLoader().getResource(testName);

        if (url != null) {
            System.setProperty(CLASSLOADER_DEPLOYED_XML, testName);
//            AspectXmlLoader.deployXML(url);
        }
   }
}